package org.best.queue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * 回环队列,回顾上面的QUEUE我们会发现造成了严重的资源浪费,
 * 不能将删除的元素的位置进行重复利用,回环队列正可以解决这个问题
 * 此代码的回环队列rear 和 front 会隔一个位置,如果不希望隔一个位置,则在check的时候直接用rear%length == front
 */
public class loopBackQueue<E> {
    private Logger log = LoggerFactory.getLogger(loopBackQueue.class);
    //头指针
    private int front;
    //尾指针
    private int rear;
    //底层数组
    private Object[] array;
    //数组长度,不指定默认为10
    private int length;
    //有效元素个数
    private int size;

    public loopBackQueue(int length) {
        this.length = length;
        this.array = new Object[length];
    }

    public loopBackQueue() {
        this.length = 10;
        this.array = new Object[length];
    }

    /**
     * 添加元素
     *
     * @param data
     */
    public void add(E data) {
        if (checkRearPosition()) {
            array[rear] = data;
            size++;
            rear = (rear + 1) % length;
        }
    }

    /**
     * 删除队列头元素
     */
    public void remove() {
        if (checkFrontPosition()) {
            size--;
            front = (front + 1) % length;
        }
    }

    /**
     * 获取队列头元素
     * @return
     */
    public E getIndex(){
        return (E)array[front];
    }

    /**
     * 获取队列尾元素
     * @return
     */
    public E getLast(){
        return (E)array[rear-1];
    }

    /**
     * 获取队列全部有效元素
     * @return
     */
    public List<E> getAll(){
        List<E> list = new ArrayList<>();
        if (rear>front){
            for (int i = front; i < rear; i++) {
                list.add((E)array[i]);
            }
        }else if (rear == front){
            //不做处理,为空
        }else {
            //rear < front
            for (int i = front ; i < length; i++) {
                list.add((E)array[i]);
            }
            for (int i = 0; i < rear; i++) {
                list.add((E)array[i]);
            }
        }
        return list;
    }

    public int size(){
        return size;
    }

    private boolean checkFrontPosition() {
        if (front > length - 1 || front < 0) {
            log.info("队列异常");
            return false;
        }
        if (front == rear) {
            log.info("队列已空");
            return false;
        }
        return true;
    }

    private boolean checkRearPosition() {
        if (rear > length - 1 || rear < 0) {
            log.info("队列异常");
            return false;
        }
        if ((rear + 1) % length == front) {
            log.info("队列已满");
            return false;
        }
        return true;
    }
}
